home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
476-500
/
disk_498
/
zoomdaemon
/
source
/
zoom-handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
15KB
|
486 lines
/*
* ZOOM-DAEMON A program that implements Zoom gadgets for all Intuition
* windows that are opened while it is running.
*
* Copyright 1989 by Davide P. Cervone.
* You may use this code, provided this copyright notice is kept intact.
*/
#include "Zoom-Handler.h"
static char *program = PROGRAM;
static char *copyright = COPYRIGHT;
struct ExtGadget *FirstZoom; /* Linked list of Zoom Gadgets */
/*
* The Image structures for the HIRES and LOWRES Zoom Gadgets
*/
static struct Image ZoomImage =
{-6,0, ZOOMWIDTH,ZOOMHEIGHT,ZOOMDEPTH, &ZoomData[0][0], 0x03,0x00, NULL};
static struct Image LR_ZoomImage =
{-4,0, LRZOOMWIDTH,LRZOOMHEIGHT,LRZOOMDEPTH, &LR_ZoomData[0][0],
0x03,0x00,NULL};
/*
* Templates for the HIRES and LOWRES Zoom Gadgets (copied when a new
* instance of a Zoom Gadget is created).
*/
static struct ExtGadget ZoomGadget =
{
NULL,NULL, NULL, 0,0,0,0, 0,
{NULL, 0,0, 21,10, GADGHCOMP | GADGIMAGE | GRELRIGHT,
RELVERIFY | TOPBORDER, SYSGADGET | BOOLGADGET, (APTR)&ZoomImage,
NULL, NULL, 0, NULL, ZOOMGADG, NULL}
};
static struct ExtGadget LR_ZoomGadget =
{
NULL,NULL, NULL, 0,0,0,0, 0,
{NULL, 0,0, 15,10, GADGHCOMP | GADGIMAGE | GRELRIGHT,
RELVERIFY | TOPBORDER, SYSGADGET | BOOLGADGET, (APTR)&LR_ZoomImage,
NULL, NULL, 0, NULL, ZOOMGADG, NULL}
};
/*
* PositionZoomGadget()
*
* Finds the position for the zoom gadget by checking for GRELRIGHT
* gadgets in the window's gadget list. Gadgets in the TOPBORDER are
* counted, but since the DEPTH gadgets are not listed with TOPBORDER
* flags set, we also check for SYSGADGETs that are GRELGADGETs but not
* GRELBOTTOM gadgets (the SIZING gadget is GRELRIGHT and GRELBOTTOM),
* the DEPTH gadgets are just GRELRIGHT). The farthest left position is
* recorded, and the Zoom Gadget is placed just to the left of that.
*/
static void PositionZoomGadget(zGadget,theWindow)
struct Gadget *zGadget;
struct Window *theWindow;
{
struct Gadget *theGadget = theWindow->FirstGadget;
int FarthestLeft = 1;
while (theGadget)
{
if ((theGadget->Flags & (GRELRIGHT|GRELBOTTOM)) == GRELRIGHT &&
theGadget->TopEdge <= zGadget->Height &&
theGadget->LeftEdge < FarthestLeft)
FarthestLeft = theGadget->LeftEdge;
theGadget = theGadget->NextGadget;
}
zGadget->LeftEdge = FarthestLeft - zGadget->Width;
}
/*
* AddZoomGadget()
*
* Allocate a new Zoom Gadget structure, and initialize it for the proper
* resolution of the window it is attached to. Set the position of the
* gadget so that it is to the left of the depth gadgets. Then link it
* into the linked list of zoom gadgets so that we can keep track of it
* (Forbid() so that the linked list does not change while we are using it).
* Add the new gadget into the window, and refresh it so that it is
* displayed properly. Since the gadget is added to the beginning of the
* list, it will lie on top of the drag bar (if any).
*/
static void AddZoomGadget(theWindow)
struct Window *theWindow;
{
ULONG Resolution = theWindow->WScreen->ViewPort.Modes & HIRES;
struct ExtGadget *theGadget;
theGadget = AllocMem(EXTGADGETSIZE,MEMFLAGS);
if (theGadget)
{
theGadget->Window = theWindow;
theGadget->Flags = 0;
if (Resolution == HIRES)
theGadget->Gadget = ZoomGadget.Gadget;
else
theGadget->Gadget = LR_ZoomGadget.Gadget;
PositionZoomGadget(&(theGadget->Gadget),theWindow);
if (theWindow->Flags & GIMMEZEROZERO)
theGadget->Gadget.GadgetType |= GZZGADGET;
Forbid();
theGadget->Prev = NULL;
theGadget->Next = FirstZoom;
if (FirstZoom) FirstZoom->Prev = theGadget;
FirstZoom = theGadget;
Permit();
AddGadget(theWindow,&(theGadget->Gadget),0);
RefreshGList(&(theGadget->Gadget),theWindow,NULL,1);
}
}
/*
* cOpenWindow()
*
* This is called after a window has been opened: theWindow is the
* pointer to the opened window.
*
* If the window gets NEWSIZE IntuiMessages, or if it includes a SIZING
* gadget, then add the Zoom Gadget. We assume that windows that do not
* include one of these are not allowed to change size, so we don't add
* Zoom Gadgets to them.
*/
struct Window *cOpenWindow(theWindow)
struct Window *theWindow;
{
if (theWindow)
{
if ((theWindow->IDCMPFlags & NEWSIZE) ||
(theWindow->Flags & WINDOWSIZING))
AddZoomGadget(theWindow);
}
return(theWindow);
}
/*
* FindZoomGadget()
*
* Look through the linked list for a gadget attached to this window
* (alternatively, we could look through the window's gadget list for
* one that has the ZOOMGADG Id, but this is probably safer).
* Do this in Forbid() mode so that the list does not change while
* we are looking at it.
*/
static struct ExtGadget *FindZoomGadget(theWindow)
struct Window *theWindow;
{
struct ExtGadget *theGadget;
Forbid();
theGadget = FirstZoom;
while (theGadget && theGadget->Window != theWindow)
theGadget = theGadget->Next;
Permit();
return(theGadget);
}
/*
* cCloseWindow()
*
* This is called before the window is closed.
*
* If a window is being closed, check to see if it has a Zoom Gadget.
* If so, then remove the gadget from the window, unlink it from
* the linked list of gadgets, and free its memory. This is done in
* Forbid() mode so that the linked list of zoom gadgets does not change
* while we are looking at it.
*/
void cCloseWindow(theWindow)
struct Window *theWindow;
{
struct ExtGadget *theGadget;
if (theWindow)
{
Forbid();
theGadget = FindZoomGadget(theWindow);
if (theGadget)
{
RemoveGadget(theWindow,&(theGadget->Gadget));
if (theGadget->Next) theGadget->Next->Prev = theGadget->Prev;
if (theGadget->Prev) theGadget->Prev->Next = theGadget->Next;
if (theGadget == FirstZoom) FirstZoom = theGadget->Next;
FreeMem(theGadget,EXTGADGETSIZE);
}
Permit();
}
}
/*
* CheckZoomMove()
*
* Called when a new gadget is being added to a window, this checks to
* see if it is first in the gadget list and that it is being added to
* a window (not a screen or requester). If so, look for a zoom gadget
* attached to this window. If one exists, then remove it temporarily,
* reposition it in relation to other GRELRIGHT gadgets, and then add it
* back at the front of the list (make sure it's displayed on top).
* Ten refresh the display so that the old image is removed and the new
* one is displayed.
*/
static void CheckZoomMove(theParent,theGadget,Position)
struct Window *theParent;
struct Gadget *theGadget;
int Position;
{
struct ExtGadget *zGadget;
if (Position == 0 && (theGadget->GadgetType & (SCRGADGET|REQGADGET)) == 0)
{
zGadget = FindZoomGadget(theParent);
if (zGadget && theGadget != &(zGadget->Gadget))
{
RemoveGadget(theParent,&(zGadget->Gadget));
PositionZoomGadget(&(zGadget->Gadget),theParent);
aOldAddGadget(theParent,&(zGadget->Gadget),0);
RefreshWindowFrame(theParent);
}
}
}
/*
* cAddGadget()
*
* This is called before the gadget is added, and we are expected to call
* aOldAddGadget somewhere in this routine. The return address is the
* position of the new gadget in the list.
*
* First we add the new gadget into the list, then check the list for
* Zoom Gadgets and reposition them as needed.
*/
int cAddGadget(theParent,theGadget,Position)
struct Window *theParent;
struct Gadget *theGadget;
int Position;
{
Position = aOldAddGadget(theParent,theGadget,Position);
CheckZoomMove(theParent,theGadget,Position);
return(Position);
}
/*
* cAddGList()
*
* This is called before the gadgets are added, and we are expected to call
* aOldAddGList somewhere in this routine. The return address is the
* position of the new gadgets in the list.
*
* First we add the new gadgets into the list, then check the list for
* Zoom Gadgets and reposition them as needed.
*/
int cAddGList(theParent,theGadget,Position,Count,theRequest)
struct Window *theParent;
struct Gadget *theGadget;
int Position;
int Count;
struct Requester *theRequest;
{
Position = aOldAddGList(theParent,theGadget,Position,Count,theRequest);
CheckZoomMove(theParent,theGadget,Position);
return(Position);
}
/*
* ResizeWindow()
*
* This routine provides a safe way to resize and move a window (the size
* and position may be changed in order to make the window fit the screen).
*
* Check to be sure the width and height are mot too big.
* Check to be sure the position makes the whole window fit on the screen.
*
* Calculate the offsets needed to make the window the right size and place
* If the new widths would take it off the screen,
* Move the window to its new position, and set the offsets to zero.
* Size the window to make it the new size.
* Move the window to its new position.
*/
static void ResizeWindow(theWindow,x,y,w,h)
struct Window *theWindow;
int x,y,w,h;
{
struct Screen *theScreen = theWindow->WScreen;
int dx,dy,dh,dw;
if (w < 0) w = theScreen->Width; else
if (w > theScreen->Width) w = theScreen->Width;
if (h < 0) h = theScreen->Height; else
if (h > theScreen->Height) h = theScreen->Height;
if (x < 0) x = 0; else
if (x + w > theScreen->Width) x = theScreen->Width - w;
if (y < 0) y = 0; else
if (y + h > theScreen->Height) y = theScreen->Height - h;
dx = x - theWindow->LeftEdge; dy = y - theWindow->TopEdge;
dw = w - theWindow->Width; dh = h - theWindow->Height;
if (theWindow->LeftEdge + w > theScreen->Width ||
theWindow->TopEdge + h > theScreen->Height)
{
MoveWindow(theWindow,dx,dy);
dx = dy = 0;
}
if (dw || dh) SizeWindow(theWindow,dw,dh);
if (dx || dy) MoveWindow(theWindow,dx,dy);
}
/*
* ZoomOutWindow()
*
* If the window has already been zoomed,
* Resize the window to its original size.
* Mark the window as not ZOOMED.
* Otherwise the window should be sized to the full size of the screen.
* If the window is not zoomed in then
* Save the window's current position and size.
* Zoom the window out to the size of the screen.
* Mark the window as ZOOMED.
*/
static void ZoomOutWindow(theGadget)
struct ExtGadget *theGadget;
{
struct Window *theWindow = theGadget->Window;
if (theGadget->Flags & EG_ZOOMEDOUT)
{
ResizeWindow(theWindow,theGadget->x,theGadget->y,
theGadget->w,theGadget->h);
theGadget->Flags = 0;
} else {
if ((theGadget->Flags & EG_ZOOMED) == 0)
{
theGadget->x = theWindow->LeftEdge;
theGadget->y = theWindow->TopEdge;
theGadget->w = theWindow->Width;
theGadget->h = theWindow->Height;
}
ResizeWindow(theWindow,0,0,theWindow->MaxWidth,theWindow->MaxHeight);
theGadget->Flags = EG_ZOOMEDOUT;
}
}
/*
* ZoomInWindow()
*
* If the window has already been zoomed,
* Resize the window to its original size.
* Mark the window as not ZOOMED.
* Otherwise the window should be sized to its minimum size.
* If the window is not zoomed out then
* Save the window's current position and size.
* Zoom the window to its smallest size.
* Mark the window as ZOOMED.
*/
static void ZoomInWindow(theGadget)
struct ExtGadget *theGadget;
{
struct Window *theWindow = theGadget->Window;
int w,h;
if (theGadget->Flags & EG_ZOOMEDIN)
{
ResizeWindow(theWindow,theGadget->x,theGadget->y,
theGadget->w,theGadget->h);
theGadget->Flags = 0;
} else {
if ((theGadget->Flags & EG_ZOOMED) == 0)
{
theGadget->x = theWindow->LeftEdge;
theGadget->y = theWindow->TopEdge;
theGadget->w = theWindow->Width;
theGadget->h = theWindow->Height;
}
w = MAX(theWindow->MinWidth,-theGadget->Gadget.LeftEdge);
h = MAX(theWindow->MinHeight,theGadget->Gadget.Height);
ResizeWindow(theWindow,theWindow->LeftEdge,theWindow->TopEdge,w,h);
theGadget->Flags = EG_ZOOMEDIN;
}
}
/*
* PressedZoomGadget()
*
* Finds the Zoom Gadget that is currently selected (if any).
* This is called from an Input Handler whenever a SELECTUP button
* event is passed to Intuition. Intuition maintains the SELECTED flag
* for the Zoom Gadgets and since the ZOOM gadgets are RELVERY BOOLGADGETs
* they will be marked SELECTED whenever the mouse is pressed and held, and
* as long as the mouse is over the gadget itself. Thus if we find a
* selected Zoom Gadget when the left mouse button is being released,
* we can be pretty sure that the user is letting go of the Zoom Gadget
* while the mouse is still over it, and thus we should process the
* gadget hit. This is done in Forbid() mode so that the linked list does
* not change while we are looking at it.
*/
static struct ExtGadget *PressedZoomGadget()
{
struct ExtGadget *theGadget;
Forbid();
theGadget = FirstZoom;
while (theGadget && (theGadget->Gadget.Flags & SELECTED) == 0)
theGadget = theGadget->Next;
Permit();
return(theGadget);
}
/*
* ZoomHandler()
*
* This is the Input Handler that checks for Zoom Gadget hits. As described
* in PressedZoomGadget() above, every time the left or right mouse button is
* released, we check to see if a Zoom Gadget is SELECTED, and assume that
* that gadget is being released. If such a gadget is found, then the
* window it is attached to is zoomed. The button event is still passed
* to Intuition so that it will know that the mouse is no longer pressed,
* and will deactivate the gadget.
*
* Since the Zoom Gadgets are marked as SYSGADGETs, Intuition will not
* send any IntuiMessages to the application about the Zoom Gadget, but since
* their types are none of the standard Intuition gadgets, Intuition
* ignores them. This saves having to monitor each windows IDCMP port for
* messages from these gadgets, which reduces the overhead both in time and
* programming.
*/
struct InputEvent *ZoomHandler(EventList,data)
struct InputEvent *EventList;
APTR data;
{
struct InputEvent *theEvent = EventList;
struct ExtGadget *theGadget;
while (theEvent)
{
if (theEvent->ie_Class == IECLASS_RAWMOUSE &&
(theEvent->ie_Code == SELECTUP || theEvent->ie_Code == MENUDOWN))
{
theGadget = PressedZoomGadget();
if (theGadget)
if (theEvent->ie_Code == MENUDOWN)
{
ZoomInWindow(theGadget);
theEvent->ie_Code = SELECTUP;
} else {
ZoomOutWindow(theGadget);
}
}
theEvent = theEvent->ie_NextEvent;
}
return(EventList);
}